#include <stdio.h>
#include <stdlib.h>

#include <tchar.h>
#include <Windows.h>

bool TestException1()
{
	bool bRet = false;
	TCHAR* pData = NULL;
	__try {
		_tcscpy(pData, _T("exception test"));
		
		bRet = true;
	} __except(EXCEPTION_EXECUTE_HANDLER) {
			
	}
	return bRet;
}

const TCHAR* GetErrorInfo(DWORD dwException, TCHAR* szExeErr)
{
	__try 
	{
		if (NULL != szExeErr)
		{
			switch (dwException)
			{
				case EXCEPTION_ACCESS_VIOLATION:			_tcscpy(szExeErr, _T("EXCEPTION_ACCESS_VIOLATION"));			break;
				case EXCEPTION_DATATYPE_MISALIGNMENT:		_tcscpy(szExeErr, _T("EXCEPTION_DATATYPE_MISALIGNMENT"));		break;   
				case EXCEPTION_BREAKPOINT:					_tcscpy(szExeErr, _T("EXCEPTION_BREAKPOINT"));					break;              
				case EXCEPTION_SINGLE_STEP:					_tcscpy(szExeErr, _T("EXCEPTION_SINGLE_STEP"));					break;             
				case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:		_tcscpy(szExeErr, _T("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));		break;   
				case EXCEPTION_FLT_DENORMAL_OPERAND :		_tcscpy(szExeErr, _T("EXCEPTION_FLT_DENORMAL_OPERAND"));		break;   
				case EXCEPTION_FLT_DIVIDE_BY_ZERO:			_tcscpy(szExeErr, _T("EXCEPTION_FLT_DIVIDE_BY_ZERO"));			break;      
				case EXCEPTION_FLT_INEXACT_RESULT:			_tcscpy(szExeErr, _T("EXCEPTION_FLT_INEXACT_RESULT"));			break;      
				case EXCEPTION_FLT_INVALID_OPERATION :		_tcscpy(szExeErr, _T("EXCEPTION_FLT_INVALID_OPERATION"));		break;  
				case EXCEPTION_FLT_OVERFLOW:				_tcscpy(szExeErr, _T("EXCEPTION_FLT_OVERFLOW"));				break;            
				case EXCEPTION_FLT_STACK_CHECK:				_tcscpy(szExeErr, _T("EXCEPTION_FLT_STACK_CHECK"));				break;         
				case EXCEPTION_FLT_UNDERFLOW:				_tcscpy(szExeErr, _T("EXCEPTION_FLT_UNDERFLOW"));				break;           
				case EXCEPTION_INT_DIVIDE_BY_ZERO:			_tcscpy(szExeErr, _T("EXCEPTION_INT_DIVIDE_BY_ZERO"));			break;      
				case EXCEPTION_INT_OVERFLOW:				_tcscpy(szExeErr, _T("EXCEPTION_INT_OVERFLOW"));				break;            
				case EXCEPTION_PRIV_INSTRUCTION:			_tcscpy(szExeErr, _T("EXCEPTION_PRIV_INSTRUCTION"));			break;        
				case EXCEPTION_IN_PAGE_ERROR:				_tcscpy(szExeErr, _T("EXCEPTION_IN_PAGE_ERROR"));				break;           
				case EXCEPTION_ILLEGAL_INSTRUCTION:			_tcscpy(szExeErr, _T("EXCEPTION_ILLEGAL_INSTRUCTION"));			break;     
				case EXCEPTION_NONCONTINUABLE_EXCEPTION:	_tcscpy(szExeErr, _T("EXCEPTION_NONCONTINUABLE_EXCEPTION"));	break;
				case EXCEPTION_STACK_OVERFLOW:				_tcscpy(szExeErr, _T("EXCEPTION_STACK_OVERFLOW"));				break;          
				case EXCEPTION_INVALID_DISPOSITION:			_tcscpy(szExeErr, _T("EXCEPTION_INVALID_DISPOSITION"));			break;     
				case EXCEPTION_GUARD_PAGE:					_tcscpy(szExeErr, _T("EXCEPTION_GUARD_PAGE"));					break;              
				case EXCEPTION_INVALID_HANDLE:				_tcscpy(szExeErr, _T("EXCEPTION_INVALID_HANDLE"));				break;          
			}
		}
	} __except (EXCEPTION_EXECUTE_HANDLER) {

	}

	return szExeErr;
}

LONG ExcFilter(DWORD dwException)
{
	TCHAR szExeErr[MAX_PATH];
	GetErrorInfo(dwException, szExeErr);
	_tprintf(_T("occour exception error, information: %s(0x%X)\n"), szExeErr, dwException);

	return EXCEPTION_EXECUTE_HANDLER;
}

LONG ExcFilter1(EXCEPTION_POINTERS* pException)
{	
	TCHAR szExeErr[MAX_PATH];
	TCHAR szStrInfo[MAX_PATH];
	if (pException->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
	{
		if (0 == pException->ExceptionRecord->ExceptionInformation[0])
		{
			_stprintf(szStrInfo, _T("%s address 0x%X error"), _T("Read"), pException->ExceptionRecord->ExceptionInformation[1]);
		} else {
			_stprintf(szStrInfo, _T("%s address 0x%X error"), _T("Write"), pException->ExceptionRecord->ExceptionInformation[1]);
		}
	} else {
		_stprintf(szStrInfo, _T("%d"), pException->ExceptionRecord->ExceptionInformation[0]);
	}

	_tprintf(_T("occour exception error, information: \n")
			 _T("Error Code:  %s\n")
			 _T("Error flags: %s\n")
			 _T("Error Address: 0x%X\n")
			 _T("Error Information: %s\n")
			 _T("NumberParameters: 0x%X\n"),
			 GetErrorInfo(pException->ExceptionRecord->ExceptionCode, szExeErr),
			 (0 == pException->ExceptionRecord->ExceptionFlags) ? _T("NonContinuable") : _T("Continuable"),
			 pException->ExceptionRecord->ExceptionAddress,
			 szStrInfo,
			 pException->ExceptionRecord->ExceptionInformation[0],
			 pException->ExceptionRecord->NumberParameters);

	return EXCEPTION_EXECUTE_HANDLER;
}

bool TestException2()
{
	bool bRet = false;
	TCHAR* pData = NULL;
	__try {
		_tcscpy(pData, _T("exception test"));
	
		bRet = true;
	} __except(ExcFilter(GetExceptionCode())) {
		_tprintf(_T("occur exception\n"));
	}
	return bRet;
}

bool TestException3()
{
	bool bRet = false;
	DWORD dwTmp = 0;
	TCHAR* pData = NULL;
	__try {
		_tcscpy(pData, _T("exception test"));

		pData = new TCHAR[100/dwTmp];
		bRet = true;
	} __except(ExcFilter1(GetExceptionInformation())) {
		_tprintf(_T("occur exception\n"));
	}
	return bRet;
}

void main()
{
	if (TestException1())
	{
		_tprintf(_T("Copy successfully"));
	} else {
		_tprintf(_T("Copy failed"));
	}

	TestException2();

	TestException3();

	system("pause");


	return;
}